package com.zhentao.controller;

// 控制层：对外提供“订单相关”的 HTTP 接口
// 说明：本文件仅添加中文注释，不改动任何业务逻辑或方法签名

import com.fasterxml.jackson.databind.JsonNode;              // 用于接收前端 JSON 请求体
import com.zhentao.mapper.OrderMainMapper;                   // 订单主表/明细/费用持久化操作
import com.zhentao.mapper.SpecValueMapper;                   // 规格字典查询（根据 spec_value_id 回填）
import com.zhentao.pojo.OrderFee;                            // 订单费用快照实体
import com.zhentao.pojo.OrderItem;                           // 订单明细实体
import com.zhentao.pojo.OrderMain;                           // 订单主表实体
import com.zhentao.pojo.SpecValue;                           // 规格字典实体
import com.zhentao.vo.Result;                                // 统一返回体
import org.springframework.beans.factory.annotation.Autowired; // 注入 Mapper
import org.springframework.transaction.annotation.Transactional; // 声明式事务
import org.springframework.web.bind.annotation.*;             // Web 注解（RestController、RequestMapping、PostMapping 等）

import java.math.BigDecimal;                                  // 金额类型（注意避免浮点误差）
import java.text.SimpleDateFormat;                            // 订单号时间格式化
import java.util.*;                                           // Date、Map、Random 等

/**
 * 订单接口控制器（User 模块）
 * Base Path: /orders
 *
 * 职责：
 * 1) 创建订单（写入订单主表 + 明细表 + 费用表）
 * 2) 对前端缺失的规格字段进行“安全回填”（根据 spec_value_id 从规格表查询 sku/name）
 *
 * 事务：
 * - @Transactional(rollbackFor = Exception.class) 确保任一写入失败将整体回滚，保持数据一致性
 *
 * 时间：
 * - create_time 使用 JVM 当前时间；请保证应用/JDBC 均设置为 Asia/Shanghai 以避免 8 小时偏差
 */
@RestController                                           // 将该类注册为 REST 控制器，返回值默认走 JSON 序列化
@RequestMapping("/orders")                               // 控制器基础路径
public class OrderController {

    @Autowired
    private OrderMainMapper orderMainMapper;              // 订单相关的数据库写入操作（主表/明细/费用）
    @Autowired
    private SpecValueMapper specValueMapper;              // 规格字典查询：按 spec_value_id 查询 skuCode/规格名

    /**
     * 创建订单
     * 入参（JSON）示例要点：
     * - userId: Long，必填
     * - type: String，可选，personal/ship，默认 personal
     * - items: Array[{productId, specValueId, skuCode?, productName?, specName?, price?, quantity?}]，必填
     * - shipInfo: Object，当 type=ship 时可选，含 shipId
     * - portId/captainName/captainPhone: 可选
     * - priceInfo: { productTotal, shippingFee, discount, totalAmount }，可选
     * 返回：orderId、orderNo
     */
    @PostMapping                                           // POST /orders
    @Transactional(rollbackFor = Exception.class)          // 发生任意 Exception 将回滚整个方法内的数据库操作
    public Result<Map<String, Object>> create(@RequestBody JsonNode body) { // @RequestBody：从请求体读取 JSON
        // 1) 基础校验：最小必需字段
        if (body.get("userId") == null) return Result.fail("userId不能为空"); // 用户ID是主键外键关联必备
        if (body.get("items") == null) return Result.fail("items不能为空");   // 明细不能为空，否则没有下单意义

        // 2) 订单主表快照（OrderMain）
        OrderMain main = new OrderMain();
        // 订单号：时间戳 + 随机数，仅示例；生产建议使用雪花ID/发号器保证有序与唯一
        main.setOrderNo("ORD" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + new Random().nextInt(999));
        main.setCreateTime(new Date());                    // 创建时间：JVM 当前时间（需保证时区正确）
        main.setUserId(body.get("userId").asLong());      // 归属用户
        String type = body.get("type") != null ? body.get("type").asText() : "personal"; // 订单类型：默认个人
        main.setOrderType("ship".equals(type) ? 2 : 1);   // 1=personal, 2=ship
        // 当为船舶订单时，尝试写入 shipId
        if (main.getOrderType() == 2 && body.get("shipInfo") != null && body.get("shipInfo").get("shipId") != null) {
            main.setShipId(body.get("shipInfo").get("shipId").asLong());
        }
        main.setPortId(body.get("portId") != null ? body.get("portId").asLong() : null);            // 关联港口（可空）
        main.setCaptainName(body.get("captainName") != null ? body.get("captainName").asText() : null); // 船长姓名（可空）
        main.setCaptainPhone(body.get("captainPhone") != null ? body.get("captainPhone").asText() : null); // 船长电话（可空）
        main.setPaymentType(1);                             // 支付方式：1=在线支付（示例）
        main.setOrderStatus(1);                             // 订单状态：1=已创建/待支付（示例）
        main.setIsAbnormal(0);                              // 是否异常：0=正常
        orderMainMapper.insertOrderMain(main);              // 持久化主单，并回填主键 orderId

        // 3) 订单明细（OrderItem）
        for (JsonNode item : body.get("items")) {         // 遍历每一条明细
            OrderItem oi = new OrderItem();
            oi.setOrderId(main.getOrderId());               // 绑定到刚创建的主单
            Long productId = item.get("productId") != null ? item.get("productId").asLong() : null; // 商品ID
            Long specValueId = item.get("specValueId") != null ? item.get("specValueId").asLong() : null; // 规格值ID
            oi.setProductId(productId);
            oi.setSpecValueId(specValueId);

            // 规格字段：优先使用前端值；如缺失，则按 spec_value_id 回填，避免非空字段写 NULL
            String skuCode = item.get("skuCode") != null ? item.get("skuCode").asText() : null;     // SKU 编码（可来自前端）
            String specName = item.get("specName") != null ? item.get("specName").asText() : null;   // 规格名称（可来自前端）
            if ((skuCode == null || skuCode.isBlank()) || (specName == null || specName.isBlank())) {  // 若有缺失
                if (specValueId != null) {
                    SpecValue sv = specValueMapper.selectById(specValueId);      // 查询规格字典
                    if (sv != null) {
                        if (skuCode == null || skuCode.isBlank()) skuCode = sv.getSkuCode(); // 回填 skuCode
                        if (specName == null || specName.isBlank()) specName = sv.getName();  // 回填 规格名
                    }
                }
            }
            // 将回填结果写入实体
            oi.setSkuCode(skuCode);
            oi.setSpecName(specName);

            oi.setProductName(item.get("productName") != null ? item.get("productName").asText() : null); // 商品名称（可空）

            BigDecimal price = BigDecimal.ZERO;             // 单价：默认为 0，parse 失败时兜底
            try {
                price = item.get("price") != null ? new BigDecimal(item.get("price").asText()) : BigDecimal.ZERO;
            } catch (Exception e) {
                price = BigDecimal.ZERO;                    // 容错：防止格式异常导致整单回滚
            }
            Integer quantity = item.get("quantity") != null ? item.get("quantity").asInt() : 1; // 数量，默认 1
            oi.setUnitPrice(price);                         // 单价
            oi.setQuantity(quantity);                       // 数量
            oi.setTotalPrice(price.multiply(new BigDecimal(quantity))); // 小计 = 单价 * 数量
            orderMainMapper.insertOrderItem(oi);            // 持久化明细
        }

        // 4) 费用快照（OrderFee）
        OrderFee fee = new OrderFee();
        fee.setOrderId(main.getOrderId());                  // 绑定主单
        JsonNode priceInfo = body.get("priceInfo");        // 前端传入的费用信息（可选）
        try {
            // 以下字段逐项容错，避免某一项格式异常导致全部失败
            fee.setProductTotal(priceInfo != null && priceInfo.get("productTotal") != null ? new BigDecimal(priceInfo.get("productTotal").asText()) : BigDecimal.ZERO);
            fee.setFreight(priceInfo != null && priceInfo.get("shippingFee") != null ? new BigDecimal(priceInfo.get("shippingFee").asText()) : BigDecimal.ZERO);
            fee.setDiscount(priceInfo != null && priceInfo.get("discount") != null ? new BigDecimal(priceInfo.get("discount").asText()) : BigDecimal.ZERO);
            fee.setPayTotal(priceInfo != null && priceInfo.get("totalAmount") != null ? new BigDecimal(priceInfo.get("totalAmount").asText()) : BigDecimal.ZERO);
        } catch (Exception e) {
            fee.setProductTotal(BigDecimal.ZERO);           // 解析失败兜底
            fee.setFreight(BigDecimal.ZERO);
            fee.setDiscount(BigDecimal.ZERO);
            fee.setPayTotal(BigDecimal.ZERO);
        }
        orderMainMapper.insertOrderFee(fee);                // 持久化费用
        return Result.success(Map.of("orderId", main.getOrderId(), "orderNo", main.getOrderNo())); // 返回关键标识供前端跳转
    }
    /**
     * 获取订单详情（标准REST风格）
     * GET /orders/{orderId}
     * 说明：返回聚合后的订单详情（主单+明细+费用），供前端订单详情页使用。
     */
    @GetMapping("/{orderId}")
    public Result<OrderMain> getOrderDetail(@PathVariable("orderId") Integer orderId) {
        OrderMain order = orderMainMapper.detailOrders(orderId);
        return Result.success(order);
    }

}
